package com.mapbased.wfw;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import javax.servlet.http.*;
import com.mapbased.wfw.handler.HttpConstants;
import com.mapbased.wfw.handler.DefaultPageHandler;

public class RenderContext
{

    private HttpServletRequest request;
    private HttpServletResponse response;
    private PageHandler pageHandler;
    private Writer writer;
    protected String remoteAddr=null;
    Map requestMap;
    String locale;
    public final GlobalRef global;
    public RenderContext(HttpServletRequest request,
                         HttpServletResponse response,GlobalRef global)
    {
        this.request=request;

        this.response=response;
        this.global=global;
        this.buildRequestMap();

        // writer=new java.io.OutputStreamWriter(response.getWriter());
    }

    /**
     * return proccess direct ,render the given page to response,
     *
     * @param pageppath String
     * @param code int
     */
    public void throwExitPage(String pageppath,int code)
    {

        Page p=this.global.getPageLoader().getPage(pageppath
            ,this.getLocale());

        try
        {
            response.setContentType(AppServlet.CONTENT_TYPE);
            response.setStatus(code);
            this.setPageHandler(p.getPageHandler());
            p.render(this);
            //response.getOutputStream().println(txt);

        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }
        throw ExitException.INSTANCE;

    }

    public String getPageExtName()
    {
        String s=this.getPageHandler().getPagePath();
        return getPageExtName(s);
    }

    public static String getPageExtName(String pagePath)
    {
        int i=pagePath.indexOf('.');
        if(i<0)
            return "";
        return pagePath.substring(i);

    }


    public void throwExit(Throwable t)
    {
        try
        {
            response.setContentType(AppServlet.CONTENT_TYPE);
            this.getOutputWriter().write("<html><body><pre>");
            response.setStatus(500);
            t.printStackTrace(new PrintWriter( this.getOutputWriter()));
            this.getOutputWriter().write("</pre></body><html>");

        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }
        throw ExitException.INSTANCE;

    }

    public void throwExit(String txt,int code)
    {
        try
        {
            response.setContentType(AppServlet.CONTENT_TYPE);
            response.setStatus(code);
            response.getWriter().println(txt);

        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }
        throw ExitException.INSTANCE;

    }

    public void throwNotFound()
    {
        try
        {
            response.sendError(404);
        }
        catch(IOException ex)
        {
        }

        throw ExitException.INSTANCE;
    }

    /**
     * careful use!
     *
     * when call from a webservice,might need to reset the remoteAddr
     * to fetch out the user info.
     *
     * @param remoteAddr String
     */
    public void setRemoteAddr(String remoteAddr)
    {
        this.remoteAddr=remoteAddr;
    }

    public String getRemoteAddr()
    {
        if(this.remoteAddr == null)
        {
            this.remoteAddr=this.request.getHeader(HttpConstants.
                __XForwardedFor);
            if(this.remoteAddr == null)
            {
                this.remoteAddr=this.request.getRemoteAddr();
            }
        }
        return this.remoteAddr;
    }

    protected void buildRequestMap()
    {
        Map m=this.request.getParameterMap();
        if(m != null)
        {
            requestMap=new java.util.HashMap(m);
        }
        else
        {
            requestMap=new java.util.HashMap(6);
        }

    }

    public Config getConfig()
    {
        return this.global.wfwConfig;
    }

    /*
            private Object[] variables;
        public Object getVariable(int index)
        {

            if(this.variables == null || variables.length <= index)
            {
                return null;
            }
            return this.variables[index];
        }

        public void setVariable(int index,Object o)
        {
            if(this.variables == null)
            {
                this.variables=new Object[index + 1];
            }
            if(this.variables.length <= index)
            {
                Object[] os=new Object[index + 1];
                System.arraycopy(this.variables,0,os,0,this.variables.length);
                this.variables=os;
            }
            this.variables[index]=o;
        }
     */
    public Map getRequestMap()
    {
        return this.requestMap;
    }

    public void putParam(String key,Object v)
    {
        requestMap.put(key,v);
    }

    /**
     *
     * @param srckey String
     * @param tagkey String
     */
    public void cloneParam(String srckey,String tagkey)
    {
        requestMap.put(tagkey,requestMap.get(srckey));
    }

    /**
     * put a validate error msg into context
     *
     * @param key String
     * @param o Object
     */
    public void putError(String key,Object o)
    {
        Map m=(Map)this.requestMap.get(Constants.Valid_Errors);
        if(m == null)
        {
            m=new HashMap(6);
            this.requestMap.put(Constants.Valid_Errors,m);
        }
        m.put(key,o);

    }

    public Map getErrors()
    {
        return(Map)this.requestMap.get(Constants.Valid_Errors);
    }

    public void removeError(String key)
    {
        Map m=(Map)this.requestMap.get(Constants.Valid_Errors);
        if(m != null)
        {
            m.remove(key);
        }

    }

    public boolean containsParam(String key)
    {
        return this.requestMap.get(key) != null;
    }

    public boolean containsError(String key)
    {
        Map m=(Map)this.requestMap.get(Constants.Valid_Errors);
        if(m != null)
        {
            return m.containsKey(key);
        }
        return false;

    }

    /**
     * tell wether there is validate errors
     * @return boolean
     */
    public boolean hasErrors()
    {
        Map m=(Map)this.requestMap.get(Constants.Valid_Errors);
        return m != null && m.size() > 0;
    }

    /**
     * Make sure there is an integer with given value in map
     *
     */

//    private static final Integer DEFAULT_ZERO_INT=new Integer(0);
    public int updateSureInt(String key)
    {
        return this.updateSureInt(key,0);

    }

    /**
     * Make sure there is an integer with given value in map
     * @param key String
     * @param defaultval Integer
     * @return Integer
     */

    public int updateSureInt(String key,int defaultval)
    {
        String s=this.getSureSingleParam(key);

        if(!s.equals(""))
        {
            try
            {
                return Integer.parseInt(s);

            }
            catch(NumberFormatException ex)
            {
            }
        }

        this.requestMap.put(key,String.valueOf(defaultval));
        return defaultval;

    }

    public String updateSureParam(String key,String defaultValue)
    {
        String value=this.getSureSingleParam(key);
        if("".equals(value))
        {

            this.requestMap.put(key,defaultValue);
            return defaultValue;
        }
        return value;
    }

    public int getSureSingleInt(String key,int defaultValue)
    {
        String s=this.getSureSingleParam(key);
        if(s.equals(""))
        {
            return defaultValue;
        }
        return Integer.parseInt(s.trim());
    }

    public int getSureSingleInt(String key)
    {
        String s=this.getSureSingleParam(key);
        if(s.equals(""))
        {
            return 0;
        }
        return Integer.parseInt(s.trim());
    }

    public boolean formatEmail(String emailKey)
    {
        String s=this.getSureSingleParam(emailKey).trim();
        if(s.equals(""))
        {
            return false;
        }
        int in=s.indexOf("@") + 1;
        if(in < 1)
        {
            return false;
        }
        char c[]=s.toCharArray();
        for(int i=in;i < c.length;i++)
        {
            c[i]=java.lang.Character.toLowerCase(c[i]);
        }
        this.putParam(emailKey,new String(c));
        return true;

    }

    /**
     * remove script from given html string
     * @param key String
     * @return String
     */

    public String removeHTMLScript(String key)
    {
        String s=this.getSureSingleParam(key);
        s=com.mapbased.wfw.Util.removeScript(s);
        this.requestMap.put(key,s);
        return s;
    }

    public String trim(String key)
    {
        String s=this.getSureSingleParam(key).trim();
        this.requestMap.put(key,s);
        return s;
    }

    /**
     * convert given string to textable js string safe
     * @param key String
     * @return String
     */

    public String toJsString(String key)
    {
        String s=this.getSureSingleParam(key);
        s=com.mapbased.wfw.Util.toJsSafe(s);
        this.requestMap.put(key,s);
        return s;

    }

    /**
     * convert "<" to "&lt;" etc
     * @param key String
     * @return String
     */
    public String toXMLSafe(String key)
    {
        String s=this.getSureSingleParam(key);
        s=com.mapbased.wfw.Util.replaceToXml(s);
        this.requestMap.put(key,s);
        return s;

    }

    public String toUrlSafe(String key)
    {



        String s=this.getSureSingleParam(key);
        try
        {
            s=java.net.URLEncoder.encode(
                s,"UTF-8");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        this.requestMap.put(key,s);
        return s;


    }

    /**
     * 取得第一个目录参数
     * @return String
     */
    public String getFirstPathParam()
    {
        String s=this.request.getServletPath();
        if(s.charAt(1) == '!')
        {
            int i=s.indexOf('/',1);
            if(i > 2)
            {
                return s.substring(2,i);
            }
            else
            {
                return "";
            }

        }
        return "";

    }

    public static void main(String ss[])
    {
        RenderContext rc=new RenderContext(null,null,null)
        {
            public void buildRequestMap()
            {
                requestMap=new java.util.HashMap();
            }
        };
        rc.putParam("e","Chy_hs@163.COm");
        rc.formatEmail("e");
        rc.setPageHandler(new DefaultPageHandler());
        rc.getPageHandler().setPagePath("df");
        System.out.println(rc.getPageExtName());

    }

//    public String getPathParam(int index)
//    {
//
//
//    }

    public String getSureSingleParam(String key)
    {
        Object o=this.requestMap.get(key);
        if(o instanceof String[])
        {

            String[] ss=((String[])o);
            if(ss.length != 1)
            {
                throw new java.lang.RuntimeException("more than one param :" +
                    key);
            }
            return ss[0];
        }
        else if(o instanceof String)
        {
            return o.toString();

        }
        else if(o == null)
        {
            return "";
        }
        else
        {
            return String.valueOf(o);
        }
    }

    public static String getStringFromMap(Map m,String key)
    {
        Object o=m.get(key);
        if(o instanceof String[])
        {
            return((String[])o)[0];
        }
        else if(o instanceof String)
        {
            return o.toString();

        }
        else if(o == null)
        {
            return "";
        }
        else
        {
            return String.valueOf(o);
        }

    }

    public String getCookie(String a)
    {

        Cookie[] c=this.request.getCookies();
        if(c != null)
        {
            for(int i=0;i < c.length;i++)
            {
                if(a.equals(c[i].getName()))
                {
                    return c[i].getValue();
                }
            }
        }
        return null;

    }

    /**
     * @todo:add code to verify the locale
     * @return String
     */
    public String getLocale()
    {
        if(this.locale == null)
        {
            this.locale=this.getSureSingleParam("_l").trim();
            if("".equals(this.locale))
            {
                Cookie[] ckes=this.request.getCookies();
                if(ckes != null)
                {
                    for(int i=0;i < ckes.length;i++)
                    {
                        if(ckes[i].getName().equals(Constants.
                            Cookie_Selected_Locale))
                        {
                            this.locale=ckes[i].getValue();
                            break;
                        }
                    }
                }
                if("".equals(this.locale))
                {
                    this.locale=this.request.getLocale().toString();

                }
            }
        }
        return this.locale;

    }

    /**
     * override this to provide buffer
     * @return Writer
     * @throws IOException
     */
    public Writer getOutputWriter()
        throws IOException
    {
        if(writer == null)
        {
            writer=this.response.getWriter();
        }
        return writer;

    }

    public HttpServletRequest getRequest()
    {
        return request;
    }

    public HttpServletResponse getResponse()
    {
        return response;
    }

    public PageHandler getPageHandler()
    {
        return pageHandler;
    }

    public void setPageHandler(PageHandler pageHandler)
    {
        this.pageHandler=pageHandler;

    }

    public void setLocale(String locale)
    {
        this.locale=locale;
    }

    public void fetchBean(Object b)
    //       throws InvocationTargetException,IllegalArgumentException,
    //     IllegalAccessException
    {
        Class c=b.getClass();
        Method[] ms=c.getMethods();
        Object[] op=new Object[1];
        for(int i=0;i < ms.length;i++)
        {
            Method m=ms[i];
            String mn=m.getName();
            Class[] cparas=m.getParameterTypes();

            if(mn.startsWith("set") && cparas.length == 1)
            {
                char[] ncs=mn.toCharArray();
                ncs[3]=Character.toLowerCase(ncs[3]);

                String attributeName=new String(ncs,3,ncs.length - 3);
                Object o=this.requestMap.get(attributeName);
                if(o == null)
                {
                    continue;
                }
                Class cp=cparas[0];
                if(o instanceof String[])
                {
                    if(cp.isAssignableFrom(o.getClass()))
                    {
                        op[0]=o;
                        try
                        {
                            m.invoke(b,op);
                        }
                        catch(InvocationTargetException ex)
                        {
                        }
                        catch(IllegalArgumentException ex)
                        {
                        }
                        catch(IllegalAccessException ex)
                        {
                        }
                        continue;

                    }

                    String[] os=(String[])o;
                    if(os.length == 0)
                    {
                        continue;
                    }
                    o=os[0];
                    /* if(o == null)
                     {
                         continue;
                     }*/

                }
                if(cp.isAssignableFrom(o.getClass()))
                {
                    op[0]=o;
                    try
                    {
                        m.invoke(b,op);
                    }
                    catch(InvocationTargetException ex1)
                    {
                    }
                    catch(IllegalArgumentException ex1)
                    {
                    }
                    catch(IllegalAccessException ex1)
                    {
                    }
                    continue;

                }
                Object ret=Util.valueOf(cp,(String)o);
                if(ret != null)
                {
                    op[0]=ret;
                    try
                    {
                        m.invoke(b,op);
                    }
                    catch(InvocationTargetException ex2)
                    {
                    }
                    catch(IllegalArgumentException ex2)
                    {
                    }
                    catch(IllegalAccessException ex2)
                    {
                    }
                }

            }
        }

    }
    /*
        final private static Class[] actionMethodPara=new Class[]
            {
            RenderContext.class};

        public final void executePageAction()
            throws Exception
        {
            // PageHandler ph=page.getPageHandler();
            //ctx.setPageHandler(ph);

            String actionMethod;
            actionMethod=request.getParameter(Constants.Page_Action);
            if(actionMethod == null || actionMethod.trim().length() == 0)
            {
                this.pageHandler.defaultAction(this);
            }
            else
            {
                Method m=this.pageHandler.getClass().getMethod(
                    actionMethod.concat("Action"),actionMethodPara);
                m.invoke(this.pageHandler,new Object[]
                         {this});
            }

        }
     */
}
